
# Copyright 2009 Mithun Chaubey 
# 
# Licensed under the Apache License, Version 2.0 (the "License"); you 
# may not use this file except in compliance with the License. You may 
# obtain a copy of the License at 
# 
#     http://www.apache.org/licenses/LICENSE-2.0
#     
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing  permissions and
# limitations under the License.

''' Module for handling Living History users '''

from google.appengine.ext import db
from google.appengine.api import users

def google_user_by_name(name):
    '''
    Returns Google API User object by google username

    @type name: string
    @param name: the google username of the user ('username'@gmail.com)
    @rtype: users.User
    @return: A Google API User
    '''
    #return users.User(name + "@gmail.com")
    usr = users.User(name + "@gmail.com")
    return usr

class lh_user(db.Model):
    '''Class for a Living History user'''
    username = db.StringProperty()
    google_user = db.UserProperty()
    permissions = db.ListProperty(str)

    def google_username(self):
        '''
        @return: The user's google username (email)
        @rtype: String
        '''
        return self.google_user.nickname()

    def all_permissions(self):
        '''
        Returns a list of all user permissions, including those inherited from groups
        @rtype: List
        '''
        perms = self.permissions
        if self.is_saved():
            for grp in self.groups():
                for perm in grp.permissions:
                    if perm not in perms:
                        perms.append(perm)

        return perms

    def has_perm(self, perm):
        '''
        Indicates whether user has a given permission
        @type perm: String
        @param perm: The name of the permission
        @rtype: Boolean
        '''
        if perm in self.all_permissions():
            return True
        else:
            return False

    def groups(self):
        '''
        Returns a list of all groups the user belongs to
        @rtype: List
        '''
        ugs = db.GqlQuery("SELECT * FROM lh_user_group "
                            "WHERE lh_user = :1", self)

        grouplist = []
        for ug in ugs:
            grouplist.append(ug.group)

        return grouplist

    def is_member(self, grp):
        '''
        Indicates whether user is a member of given group
        @type grp: Group
        @param grp: A Group object
        @rtype: Boolean
        '''
        query = db.GqlQuery("SELECT * FROM lh_user_group "
                            "WHERE lh_user = :1 "
                            "AND group = :2",
                            self, grp)
        if (query.get() == None):
            return False
        else:
            return True

    def add_group(self, grp):
        '''
        Adds a user to a group

        @type grp: Group
        @param grp: A Group object
        '''
        if(grp != None):
            if not self.is_member(grp):
                ug = lh_user_group()
                ug.lh_user = self.key()
                ug.group = grp.key()
                ug.put()

    def del_group(self, grp):
        '''
        Deletes a user from a group

        @type grp: Group
        @param grp: A Group object
        '''
        if self.is_member(grp):
            query = db.GqlQuery("SELECT * FROM lh_user_group "
                                "WHERE lh_user = :1 "
                                "AND group = :2",
                                self, grp)

            ug = query.get()
            ug.delete()

    def set_groups(self, groups):
        '''
        Sets a users group based on a list

        @type groups: List
        @param groups: A list of Group objects
        '''

        for grp in self.groups():
            self.del_group(grp)

        for grp in groups:
            self.add_group(grp)

class group(db.Model):
    '''A user group, established for permissions'''
    name = db.StringProperty()
    permissions = db.ListProperty(str)        

class lh_user_group(db.Model):
    '''Connecting class for many-to-many data relationship'''
    lh_user = db.ReferenceProperty(lh_user)
    group = db.ReferenceProperty(group)

def group_by_name(name):
    '''
    Returns group by name
    @type name: String
    @param name: The name of a group
    @rtype: group
    '''
    query = db.GqlQuery("SELECT * FROM group WHERE name = :1", name)
    return query.get()

def user_by_username(username):
    '''
    Returns user matching the username
    @type name: String
    @param name: A username
    @rtype: lh_user
    '''
    query = db.GqlQuery("SELECT * FROM lh_user WHERE username = :1", username)
    return query.get()

def user_by_google_user(google_user):
    '''
    Returns user matching the given google_user object
    @param google_user: A Google API User object
    @type google_user: users.User
    @rtype: lh_user
    '''
    query = db.GqlQuery("SELECT * FROM lh_user WHERE google_user = :1", google_user)
    return query.get()

def user_by_google_name(name):
    '''
    Returns user with given google username
    @type name: String
    @param name: Google username
    @rtype: lh_user
    '''
    google_user = google_user_by_name(name)
    return user_by_google_user(google_user)

def get_current_user(self):
    '''
    Returns the user currently logged in, or an unauthenticated user object
    @type self: webapp.RequestHandler
    @param self: The RequestHandler object from the calling handler
        function/class
    @rtype: lh_user
    '''
    # Check Google authentication
    google_user = users.get_current_user()
    
    # If not logged into Google, create Anon user
    if not google_user:
        user = lh_user()
        user.username = 'Anonymous'
        user.is_authenticated = False
        user.perms = {}
        user.log_url = users.create_login_url(self.request.uri)
    
    else:
        
        # Check for existing user properties
        user = user_by_google_user(google_user)
        
        # If properties exist
        if user != None:
            user.perms = {}
            for perm in user.all_permissions():
                user.perms[perm] = True
                
        # If not, add properties
        else:
            user = lh_user()
            user.username = google_user.nickname()
            user.google_user = google_user
            user.perms = {}
        
        user.is_authenticated = True
        user.log_url = users.create_logout_url(self.request.uri)

    return user
